import 'package:flutter/material.dart';

void main() {
  runApp(
    MaterialApp(
      home: _Home(),
    ),
  );
}

class _Home extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _HomeState();
  }
}

class _HomeState extends State<_Home> with SingleTickerProviderStateMixin {
  final List<String> _list = List.generate(13, (index) {
    return "images/pic${index + 1}.jpg";
  });
  AnimationController _controller;

  @override
  void initState() {
    _controller = AnimationController(
        vsync: this, duration: const Duration(milliseconds: 500));

    super.initState();
  }

  @override
  void dispose() {
    _controller?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text("SlideTransition Demo"),
          actions: <Widget>[
            IconButton(
              icon: Icon(Icons.delete),
              onPressed: () {
                if (_list.isNotEmpty) {
                  _list.removeAt(0);
                  setState(() {});
                }
              },
            )
          ],
        ),
        body: SizedBox.expand(
          child: ListView.builder(
            itemExtent: 200.0,
            itemBuilder: (context, index) {
              return _buildItem(index);
            },
            itemCount: (_list.length + 1) ~/ 2,
          ),
        ));
  }

  Widget _buildItem(int index) {
    var isOdd = index.isOdd;
    var length = _list.length;
    // 2*index = length - 2
    var noPadding = length.isOdd && (length - 1) ~/ 2 == index;
    List<Widget> _items = [];
    _items.add(Expanded(
      flex: isOdd ? 4 : 6,
      child: Padding(
        padding: EdgeInsets.only(right: noPadding ? 0.0 : 5.0),
        child: _ItemView(_list[index * 2]),
      ),
    ));
    if (index * 2 + 1 <= length - 1) {
      _items.add(Expanded(
        flex: isOdd ? 6 : 4,
        child: _ItemView(_list[index * 2 + 1]),
      ));
    }
    return Padding(
      child: Row(
        children: _items,
      ),
      padding: EdgeInsets.all(5.0),
    );
  }
}

class _ItemView extends StatefulWidget {
  final String _assetPath;

  _ItemView(this._assetPath);

  @override
  State<StatefulWidget> createState() {
    return _ItemViewState();
  }
}
/// TODO ListView 的item在有item被delete掉的时候会调用`didUpdateWidget`方法，从这里可以获取到item remove的调用时机以及数据
/// `SlideTransition`配合ClipRect使用
/// Positioned.fill--->等价于fit: StackFit.expand,
/// StackFit.loose--->不大于parent传递过来的限制的尺寸，可能是0-max之间的任何尺寸
/// StackFit.expand--->MATCH_PARENT
/// StackFit.passThrough-->将parent的约束传递给子控件
class _ItemViewState extends State<_ItemView>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;
  Animation<Offset> _oldRemove, _newAdd;
  _ItemView _oldWidget, _newWidget;

  @override
  void initState() {
    _oldWidget = widget;

    _controller = AnimationController(
        vsync: this, duration: const Duration(milliseconds: 1500));

    var beginOld = Offset(0.0, 0.0);
    var endOld = Offset(-1.0, 0.0);
    _oldRemove = Tween(begin: beginOld, end: endOld).animate(_controller);
    var beginNew = Offset(1.0, 0.0);
    var endNew = Offset(0.0, 0.0);
    _newAdd = Tween(begin: beginNew, end: endNew).animate(_controller);
    super.initState();
  }

  @override
  void dispose() {
    _controller?.dispose();
    super.dispose();
  }

  @override
  void didUpdateWidget(_ItemView oldWidget) {
    super.didUpdateWidget(oldWidget);
    print("didUpdateWidget..........");
    if (oldWidget._assetPath != widget._assetPath) {
      print(
          "didUpdateWidget:oldPath->${oldWidget._assetPath}  newPath:${widget._assetPath}");
      setState(() {
        _oldWidget = oldWidget;
        _newWidget = widget;
      });
      _replace();
    }
  }

  Future _replace() async {
    try {
      await _controller?.forward()?.orCancel;
      setState(() {
        _oldWidget = widget;
        _newWidget = null;
        _controller?.value = 0.0;
      });
    } catch (e) {
      print("_replace error:$e");
    }
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      fit: StackFit.expand,
      children: <Widget>[
        Positioned.fill(
          child:
        ClipRect(
          child: SlideTransition(
            position: _oldRemove,
            child: Image.asset(
              _oldWidget?._assetPath,
              fit: BoxFit.cover,
            ),
          ),
        ),
        ),
        Positioned.fill(
            child:
        ClipRect(
            child: SlideTransition(
          position: _newAdd,
          child: _newWidget == null
              ? null
              : Image.asset(
                  _newWidget._assetPath,
                  fit: BoxFit.cover,
                ),
        ))
    )
      ],
    );
  }
}
